/**
 * Notify创建消息通信websocket连接
 */
import {
  $wuxNotification
} from '../components/index.js';

const config = require('./config')

export default class Notify {
  constructor(app) {
    this.connectStatus = false; // websocket 连接状态
    this.heartListen = null; // 心跳包
    this.watcherFnList = []; //消息订阅者（函数）
    this.watcherPageList = []; //消息订阅者（page对象）
    this.app = app; // app对象
    this.timer = null; // 定时器
    this.socketTask = null; // websocket对象
    this.hide = null; // 返回的隐藏函数
    this.notHandleUid = null; // 全局websocket监听器不处理的uid（聊天窗口只能打开一个）
  }

  // 建立websocket连接
  connectSocket() {
    let that = this;
    if (that.connectStatus) {
      return
    }
    this.socketTask = wx.connectSocket({
      url: config.WSS_URL,
      header: {
        'content-type': 'application/json',
        'token': wx.getStorageSync("token")
      },
      method: 'POST',
      success: function (res) {
        that.connectStatus = true;
        console.debug("wss suc, status: " + that.connectStatus);
      },
      fail: function (res) {
        that.connectStatus = false;
        console.debug("wss fail, status: " + that.connectStatus);
      }
    });

    // 监听websocket打开事件
    this.socketTask.onOpen(function (res) {
      that.connectStatus = true;
      console.log("websocket已打开")
      that.addWatcher(that.commomWatcher, that);
    });

    // 监听websocket错误事件
    this.socketTask.onError(function (err) {
      that.connectStatus = false;
      clearInterval(that.timer); // 清空定时器
      console.log('监听到 WebSocket 打开错误，请检查！');
    });

    // 监听websocket关闭事件
    this.socketTask.onClose(function (res) {
      that.connectStatus = false;
      clearInterval(that.timer); // 清空定时器
      console.log("连接关闭 code:" + res.code + ", reason:" + res.reason + ", status:" + that.connectStatus);
    });

    // 监听服务器发送的消息
    this.socketTask.onMessage(function (res) {
      let data = JSON.parse(res.data);
      that.publish(data);
    });

    // 发送心跳包给服务器，并保存定时器地址
    this.timer = setInterval(function () {
      let data = JSON.stringify({
        type: config.MSG_TYPE.KEEPALIVE.type
      });
      if (that.connectStatus) {
        // console.log("发送的心跳包: " + data);
        that.socketTask.send({
          data: data,
          success: function (res) {
            // console.log(res);
          },
          fail: function (res) {
            that.connectStatus = false;
            that.reconnect();
          }
        });
      } else {
        if (wx.getStorageSync('token')) {
          console.log("重连websocket服务器ing");
          that.reconnect();
        } else {
          console.log('token无效!')
        }
      }
    }, 1000 * 10);
  }

  // 重连
  reconnect() {
    console.log('正在尝试重连...');
    // 重连之前手动关闭一次
    wx.closeSocket({
      code: 1000
    });
    this.connectSocket();
  }

  // 关闭websocket
  closeSocket() {
    let that = this;
    this.socketTask.close({
      success: res => {
        that.watcherPageList = [];
        that.watcherFnList = [];
        console.log("websocket 连接已关闭！")
      }
    })
  }

  // 添加watcher订阅者
  addWatcher(fn, pageObj) {
    this.watcherFnList.push(fn);
    this.watcherPageList.push(pageObj);
    return this.watcherFnList.length - 1; // 返回添加位置的下标，Page unload的时候方便删除List成员
  }

  // 删除watcher订阅者
  delWatcher(index) {
    this.watcherFnList.splice(index, 1);
    this.watcherPageList.splice(index, 1);
    console.log('销毁后现有watcher fn', this.watcherFnList);
    console.log('销毁后现有watcher page', this.watcherPageList);
  }

  // 发布
  publish(msg) {
    let that = this;
    this.watcherFnList.forEach(
      (fn, index) => fn(msg, that.watcherPageList[index])
    )
  }

  // 设置全局公共消息handler不处理的uid
  setNotHandleUid(uid) {
    this.notHandleUid = uid;
  }

  // 判断该用户的消息是否需要全局处理
  supportUid(uid) {
    if (this.notHandleUid && this.notHandleUid == uid) {
      return false;
    }
    return true;
  }

  // 向服务端返回客户端ack
  ack(chatId, targetUid) {
    if (!chatId) {
      return;
    }
    // 构造ack消息体
    let ack = JSON.stringify({
      id: chatId,
      type: config.MSG_TYPE.CLIENT_ACK.type,
    });
    this.socketTask.send({
      data: ack,
      success: function(res) {
        console.log("消息返回ack成功，消息id为：" + chatId)
      },
      fail: function(res) {
        console.warn("返回ack失败了，待服务器重发")
      }
    });
    // 缓存最新聊天id todo 暂时注释掉，便于测试
    // wx.setStorageSync('lastChat:' + targetUid, chatId);
    console.log("注意目前关闭了最新chatId缓存，请注意试验完后打开");
  }

  // 全局公共消息处理
  commomWatcher(data, that) {
    console.log("全局websocket监听器收到消息（消息内容略）");
    let token = wx.getStorageSync('token');
    if (!token) {
      console.log('用户登陆过期');
    }
    switch (data.type) {
      case config.MSG_TYPE.RECEIVED_INVITATION.type:
        that.hide = $wuxNotification().show({
          title: '入队邀请',
          text: data.content,
          duration: 3000,
          onClick() {
            that.hide();
          }
        });
        break;
      case config.MSG_TYPE.RECEIVED_APPLICATION.type:
        that.hide = $wuxNotification().show({
          title: '入队申请',
          text: data.content,
          duration: 3000,
          onClick() {
            that.hide();
          }
        });
        break;
      case config.MSG_TYPE.COMMENT.type:
        that.hide = $wuxNotification().show({
          title: `${data.msg.fromNickname}${data.msg.parentCommentId ? ' 回复你的评论' : ' 回复你的帖子'}`,
          text: `${data.msg.content}...`,
          image: data.msg.fromAvatar,
          duration: 3000,
          onClick() {
            that.hide();
          }
        });
        break;
      case config.MSG_TYPE.SINGLE_TEXT_MSG.type:
        if (that.supportUid(data.fromUid)) {
          that.ack(data.id);
        }
        break;
      case config.MSG_TYPE.SINGLE_IMG_MSG.type:
        if (that.supportUid(data.fromUid)) {
          that.ack(data.id);
        }
        break;
    }
  }
}